package com.lutzyt.delivery.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lutzyt.delivery.bean.Commodity;
import com.lutzyt.delivery.bean.Order;
import com.lutzyt.delivery.bean.OrderItem;
import com.lutzyt.delivery.bean.Shop;
import com.lutzyt.delivery.mapper.CommodityDAO;
import com.lutzyt.delivery.service.CommodityService;
import com.lutzyt.delivery.service.OrderItemService;
import com.lutzyt.delivery.service.ShopService;
import com.lutzyt.delivery.util.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author zyt
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class CommodityServiceImpl extends ActionServiceImpl<CommodityDAO, Commodity> implements CommodityService {

  private CommodityDAO commodityDAO;
  private ShopService shopService;
  private OrderItemService orderItemService;
  public static final int MAX_HOT_COMMODITY = 10;
  private static final String PUT_AWAY = "PUT_AWAY";

  @PostConstruct
  public void init(){
    setOn("PUT_AWAY");
    setOff("SOLD_OUT");
    setOnStr("该商品已上架，请不要重复操作!");
    setOffStr("该商品已下架，请不要重复操作");
  }

  @Transactional(readOnly = true)
  @Override
  public Commodity findById(Integer id) {
    return commodityDAO.selectById(id);
  }

  @Transactional(readOnly = true)
  @Override
  public IPage<Commodity> findByPage(int pageNum, int pageSize) {
    final QueryWrapper<Commodity> queryWrapper = new QueryWrapper<>();
    final Page<Commodity> commodityPage = commodityDAO.selectPage(new Page<>(pageNum, pageSize), queryWrapper);
    // 设置店铺名称
    commodityPage.getRecords().forEach(this::setShopName);
    return commodityPage;
  }

  @Override
  public Page<Commodity> auditPage(Integer pageNum, Integer pageSize) {
    final Page<Commodity> commodityPage = CommodityService.super.auditPage(pageNum, pageSize);
    commodityPage.getRecords().forEach(this::setShopName);
    return commodityPage;
  }

  /**
   * 设置商品店铺名称
   * @param commodity
   */
  private void setShopName(Commodity commodity){
    final Shop shop = shopService.findById(commodity.getShopId());
    commodity.setShopName(shop.getName());
  }

  @Override
  public List<Commodity> hot() {
    // 本月开始时间
    final Date beginDayOfMonth = DateUtils.getBeginDayOfMonth();
    // 获取本月前十的商品id
    final List<OrderItem> items = orderItemService.query()
        .select("commodity_id")
        .groupBy("commodity_id")
        .orderByDesc("count(commodity_id)")
        .ge("create_time", beginDayOfMonth)
        .last("limit "+MAX_HOT_COMMODITY).list();
    final List<Integer> commodityIds = items.stream().map(OrderItem::getCommodityId).collect(Collectors.toList());
    // 获取本月销量前十的商品，如果本月没有售出任何商品，则会默认取十条商品
    final List<Commodity> commodityList = this.lambdaQuery()
        .in(!commodityIds.isEmpty(), Commodity::getId, commodityIds)
        .eq(Commodity::getDeleted, 0)
        .eq(Commodity::getAudit, "PASS")
        .eq(Commodity::getState, PUT_AWAY)
        .last("limit "+MAX_HOT_COMMODITY).list();
    // 如果商品不够十条，则就在从商品中补足10个
    if (commodityList.size() < MAX_HOT_COMMODITY && !commodityIds.isEmpty()){
      final List<Commodity> list = this.lambdaQuery()
          // 排除上述有过的
          .notIn(!commodityIds.isEmpty(), Commodity::getId, commodityIds)
          // 补足缺少的个数
          .eq(Commodity::getDeleted, 0)
          .eq(Commodity::getAudit, "PASS")
          .eq(Commodity::getState, PUT_AWAY)
          .last("limit " + (MAX_HOT_COMMODITY - commodityIds.size()))
          .list();
      // 加入到推荐中
      commodityList.addAll(list);
    }
    // 补足店铺名
    commodityList.forEach(this::setShopName);
    return commodityList;
  }

  @Override
  public void insert(Commodity commodity) {
    commodityDAO.insert(commodity);
  }

  @Override
  public void update(Commodity commodity) {
    commodityDAO.updateById(commodity);
  }

  @Override
  public void deleteById(Integer id) {
    commodityDAO.deleteById(id);
  }

  @Autowired
  public void setOrderItemService(OrderItemService orderItemService) {
    this.orderItemService = orderItemService;
  }

  @Autowired
  public void setCommodityDAO(CommodityDAO commodityDAO) {
    this.commodityDAO = commodityDAO;
  }

  @Autowired
  public void setShopService(ShopService shopService) {
    this.shopService = shopService;
  }
}